﻿using RobotRemoteController;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RescueRobotController
{
    public enum ATCmdType
    {
        SET, GET, EXEC
    }
    public struct ATCmd
    {
        public ATCmdType type;
        public string target;
        public string value;
    }
    public class ATCommandParser
    {
        #region 事件定义
        public delegate void ReceivedATCmdHandler(ATCmd cmd);
        public event ReceivedATCmdHandler ReceivedATCmd;
        #endregion

        FiniteStateMachine<char> serialFSM = null;

        // AT指令解析结果
        private string ATTarget = null;
        private string ATValue = null;

        public ATCommandParser() 
        {
            // 创建状态机对象
            serialFSM = new FiniteStateMachine<char>("START");

            // 初始化状态机
            InitATCommandFSM();

            // 初始化AT指令结果变量
            ATTarget = "";
            ATValue = "";
        }

        public void Next(char ch)
        {
            serialFSM.Next(ch);
        }

        private void InitATCommandFSM()
        {
            serialFSM.AddState("START", (input) =>
            {
                if (input == 'A') return "S1";
                else return "START";
            })
            .AddState("S1", (input) =>
            {
                if (input == 'T') return "S2";
                else return "START";
            })
            .AddState("S2", (input) =>
            {
                if (input == '\n' || input == '\r')
                {
                    // 一个单独的AT指令
                    ATTarget = "AT";
                    // 调用对应事件
                    if (ReceivedATCmd != null)
                        ReceivedATCmd(new ATCmd() { type = ATCmdType.EXEC, target = "AT"});
                    return "START";
                }
                else if (input == '+')
                {
                    ATTarget = "";
                    return "S3";
                }
                else return "START";
            })
            .AddState("S3", (input) =>
            {
                if (char.IsLetterOrDigit(input) || input == '_')
                {
                    ATTarget += input;
                    return "S3";
                }
                else if (input == '=')
                {
                    ATValue = "";
                    return "S4";
                }
                else if (input == '\n' || input == '\r')
                {
                    // 无参数AT指令
                    // 调用对应事件
                    if (ReceivedATCmd != null)
                        ReceivedATCmd(new ATCmd() { type = ATCmdType.EXEC, target = ATTarget });
                    return "START";
                }
                else if (input == '?')
                {
                    return "S5";
                }
                else
                {
                    ATTarget = "";
                    return "START";
                }
            })
            .AddState("S4", (input) =>
            {
                if (input != '\n' && input != '\r')
                {
                    ATValue += input;
                    return "S4";
                }
                else if(input == '\n' || input == '\r')
                {
                    // 设置变量值
                    if (ReceivedATCmd != null)
                        ReceivedATCmd(new ATCmd() { type = ATCmdType.SET, target = ATTarget, value = ATValue });
                    return "START";
                }
                else
                {
                    return "START";
                }
            })
            .AddState("S5", (input) =>
            {
                if (input == '\n' || input == '\r')
                {
                    //查询变量值
                    if (ReceivedATCmd != null)
                        ReceivedATCmd(new ATCmd() { type = ATCmdType.GET, target = ATTarget });
                    return "START";
                }
                else
                {
                    return "START";
                }
            });
        }

        public static string[] SplitTarget(ATCmd cmd, char[] symbols=null)
        {
            string target = cmd.target;
            char[] splitSymbols = symbols == null ? new char[] { '_' }: symbols;

            string[] targetArray = target.Split(splitSymbols);

            return targetArray;
        }

    }
}
